Install Giotto, GiottoData and the Giotto environmment

if(!"Giotto" %in% installed.packages()) {
  devtools::install_github("drieslab/Giotto@suite", force = TRUE)
}
library("Giotto")
Giotto Suite 3.2
if(!"GiottoData" %in% installed.packages()) {
  remotes::install_github("drieslab/GiottoData")
}
library(GiottoData)
GiottoData 0.2.0
genv_exists <- checkGiottoEnvironment()

 giotto environment found at 
/Users/graham/Library/r-miniconda/envs/giotto_env/bin/pythonw
if(!genv_exists){
  # The following command need only be run once to install the Giotto environment.
  installGiottoEnvironment(force_environment = TRUE)
  
# library("tidyverse")
}

Create the Giotto object

results_folder = "Giotto_Results"

instrs = createGiottoInstructions(save_dir = results_folder,
                                  save_plot = TRUE,
                                  show_plot = TRUE)

no external python path was provided, but a giotto python environment was found
 and will be used
## provide path to visium folder
data_path<- "/Users/graham/Documents/Polyomics/Pr2029/run1/D1/outs/"

## directly from visium folder
visium_giotto_object <- createGiottoVisiumObject(visium_dir = data_path,
                                        expr_data = 'raw',
                                        png_name = 'tissue_lowres_image.png',
                                        gene_column_index = 2,
                                        instructions = instrs,
                                        do_manual_adj = TRUE,
                                        xmax_adj = 248,
                                        xmin_adj = 365,
                                        ymax_adj = 460,
                                        ymin_adj = 200)
A structured visium directory will be used 
do_manual_adj == TRUE 
 Boundaries will be adjusted by given values.
Consider to install these (optional) packages to run all possible Giotto
 commands for spatial analyses: MAST tiff biomaRt trendsceek RTriangle
 FactoMineR
Giotto does not automatically install all these packages as they are not
 absolutely required and this reduces the number of dependencies
List of 1
 $ raw:Formal class 'dgTMatrix' [package "Matrix"] with 6 slots
  .. ..@ i       : int [1:22993081] 2256 5031 8135 8139 8154 8165 8194 8230 8232 8277 ...
  .. ..@ j       : int [1:22993081] 0 0 0 0 0 0 0 0 0 0 ...
  .. ..@ Dim     : int [1:2] 29811 4992
  .. ..@ Dimnames:List of 2
  .. .. ..$ : Named chr [1:29811] "Tb07.11L3.90" "Tb07.11L3.100" "Tb05.5K5.20" "Tb05.5K5.30" ...
  .. .. .. ..- attr(*, "names")= chr [1:29811] "1" "2" "4" "5" ...
  .. .. ..$ : Named chr [1:4992] "AAACAACGAATAGTTC-1" "AAACAAGTATCTCCCA-1" "AAACAATCTACTAGCA-1" "AAACACCAATAACTGC-1" ...
  .. .. .. ..- attr(*, "names")= chr [1:4992] "1" "2" "3" "4" ...
  .. ..@ x       : num [1:22993081] 1 1 1 1 1 1 1 2 1 2 ...
  .. ..@ factors : list()
NULL
list depth of 1 
Warning: No default for spat_unit could be set 
Warning: No default for feat_type could be set 
finished expression data
List of 1
 $ raw:Classes ‘data.table’ and 'data.frame':   4992 obs. of  2 variables:
  ..$ sdimx: int [1:4992] 1580 520 1246 1550 615 1672 1622 1254 1785 583 ...
  ..$ sdimy: int [1:4992] -181 -1264 -247 -1453 -488 -1107 -1194 -1756 -1516 -1501 ...
  ..- attr(*, ".internal.selfref")=<externalptr> 
NULL
list depth of 1 
finished spatial location data
finished cell metadata
finished feature metadata
No spatial networks are provided
No spatial enrichment results are provided
No dimension reduction results are provided
No nearest network results are provided
# Show images associated with Giotto object
showGiottoImageNames(visium_giotto_object)
Image type: image 

--> Name: image 
# Check metadata
pDataDT(visium_giotto_object)

## show plot
slide_image <- spatPlot2D(gobject = visium_giotto_object, 
                          cell_color = 'in_tissue',
                          point_size = 2,
                          cell_color_code = c('0' = 'lightgrey', '1' = 'blue'),
                          show_image = T, 
                          image_name = 'image')


slide_image

Process Giotto Visium object

Filter

Filters are based on: expression_threshold - set the minimum expression level feat_det_in_min_cells - set the minimum number of cells that expresses a feature/gene min_det_feats_per_cell - set the minimum number of features/genes expressed per cell

filterDistributions(visium_giotto_object, detection = 'cells')

filterDistributions(visium_giotto_object, detection = 'feats')

This is a visualisation showing the number of features lost based on the various filtering parameters

filterCombinations(gobject = visium_giotto_object, 
                   expression_thresholds = c(1, 2, 3),
                   feat_det_in_min_cells = c(2, 5, 10), 
                   min_det_feats_per_cell = c(100, 200, 500))
$results

$ggplot

Use the plots above to inform the cutoff parameters for filterGiotto. In this example, an expression value of 1, feat_det_in_min_cells of 10 and min_det_feats_per_cell of 200. Also, filter out spot not covered by the tissue.

## subset on spots that were covered by tissue
metadata <- pDataDT(visium_giotto_object)
in_tissue_barcodes <- metadata[in_tissue == 1]$cell_ID
visium_giotto_object <- subsetGiotto(visium_giotto_object, cell_ids = in_tissue_barcodes)
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  1 
sys parent:  0 
visium_giotto_object <- filterGiotto(gobject = visium_giotto_object,
                             expression_threshold = 1,
                             feat_det_in_min_cells = 10,
                             min_det_feats_per_cell = 200,
                             expression_values = c('raw'),
                             verbose = T)
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  2 
sys parent:  1 

Feature type:  rna 
Number of cells removed:  25  out of  2720 
Number of feats removed:  6951  out of  29811 

Normalize the expression matrix

There are three normalisation algorythms: Standard - Normailses the data by library size and a custom scale factor, then log transforms and z-scores the data by genes or cells, which is specified by scale_order. The scale_order options are first_feats or first_cells.

visium_giotto_object <- normalizeGiotto(gobject = visium_giotto_object, 
                                norm_methods = "standard", 
                                scale_feats = TRUE,
                                scalefactor = 6000, 
                                scale_order = "first_feats",
                                verbose =TRUE)

 first scale feats and then cells 

pearson_resid - Expected values calculated based on Pearson correlations, z-scores are then calculated based on the observed values and the calculated expected values.

visium_giotto_object <- normalizeGiotto(gobject = visium_giotto_object, 
                                norm_methods = "pearson_resid", 
                                scale_feats = TRUE,
                                scalefactor = 6000, 
                                scale_order = "first_feats",
                                verbose =TRUE)
using 'Lause/Kobak' method to normalize count matrix If used in published research, please cite:
  Jan Lause, Philipp Berens, Dmitry Kobak (2020).
                      'Analytic Pearson residuals for normalization of single-cell RNA-seq UMI data' 

 Pearson residual normalized data will be returned to the scaled Giotto slot 

> scaled already exists and will be replaced with new values

osmFISH - This normalisation method is for in situ RNA data using a method described in Codeluppi et al. Feature/gene counts are normalised individually by the total feature/gene count and then multiplied by the total number of features/genes. Then, cells are individually normalised by dividing the normalised feature counts by the total feature counts per cell, then scaled by the total number of cells. This method is not shown as the data is unlikely to be from in situ RNA experiments. However, to use the algorithm can specify “osmFISH” as the argument for norm_methods.

```r
# visium_giotto_object <- normalizeGiotto(gobject = visium_giotto_object, 
#                                 norm_methods = \osmFISH\, 
#                                 scale_feats = TRUE,
#                                 scalefactor = 6000, 
#                                 verbose =TRUE)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



## Add gene & cell statistics and metadata
The function addStatistics will add the following statistics to cell metadata:
**nr_feats** - Denotes how many features are detected per cell
**perc_feats** - Denotes the percentage of features detected per cell
**total_expr** - Shows the total sum of feature expression per cell

It will also add the following statistics to feature metadata:
**nr_cells** - Denotes how many cells in which the feature is detected
**per_cells** - Denotes the percentage of cells in which the feature is detected
**total_expr** - Shows the total sum of feature expression in all cells
**mean_expr** - Average feature expression in all cells
**mean_expr_det** - Average feature expression in cells with detectable levels of the feature


<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxudmlzaXVtX2dpb3R0b19vYmplY3QgPC0gYWRkU3RhdGlzdGljcyhnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QpXG5cbiMgQWNjZXNzb3JzOlxuY2VsbF9tZXRhZGF0YSA8LSBwRGF0YURUKHZpc2l1bV9naW90dG9fb2JqZWN0KVxuZmVhdHVyZV9tZXRhZGF0YSA8LSBmRGF0YURUKHZpc2l1bV9naW90dG9fb2JqZWN0KVxuXG4jIGNhbGN1bGF0ZSBwZXJjZW50YWdlIG9mIG1pdG9jaG9uZHJpYWwgY29udGVudCBwZXIgc3BvdFxubWl0b2Nob25kcmlhbF9nZW5lcyA8LSBncmVwKCdebXQtJywgdmlzaXVtX2dpb3R0b19vYmplY3RAZmVhdF9JRCRybmEsIHZhbHVlID0gVClcbnZpc2l1bV9naW90dG9fb2JqZWN0IDwtIGFkZEZlYXRzUGVyYyhnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZlYXRzID0gbWl0b2Nob25kcmlhbF9nZW5lcywgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlY3Rvcl9uYW1lID0gJ21pdG8nKVxuXG5gYGAifQ== -->

```r
visium_giotto_object <- addStatistics(gobject = visium_giotto_object)

# Accessors:
cell_metadata <- pDataDT(visium_giotto_object)
feature_metadata <- fDataDT(visium_giotto_object)

# calculate percentage of mitochondrial content per spot
mitochondrial_genes <- grep('^mt-', visium_giotto_object@feat_ID$rna, value = T)
visium_giotto_object <- addFeatsPerc(gobject = visium_giotto_object,
                             feats = mitochondrial_genes, 
                             vector_name = 'mito')

View the gene and cells statistics

head(fDataDT(visium_giotto_object)) 
head(pDataDT(visium_giotto_object))

Visualise the number of features/genes and mitochondrial genes per cell


# Visualize number of genes and mitochondrial content per spot
spatPlot2D(gobject = visium_giotto_object,
           show_image = TRUE,
           point_alpha = 1,
           cell_color = 'nr_feats', color_as_factor = F,
           coord_fix_ratio = 1)


spatPlot2D(gobject = visium_giotto_object,
           show_image = TRUE,
           point_alpha = 1,
           cell_color = 'mito', color_as_factor = F,
           coord_fix_ratio = 1)

Adjust for technical co-founders

Adjust expression matrix for known batch effects or technological covariates. In this case use the mitochondrial genes as a covariate and regress the number of features detected per cell, this means that these covariates will not affect further analyses.

visium_giotto_object <- adjustGiottoMatrix(gobject = visium_giotto_object, 
                                   covariate_columns = c("nr_feats", "mito"), 
                                   update_slot = "custom")

Dimension reduction

Prior to running cluster analysis it is best to do feature selection to retain the most informative features/genes to optimise signal to noise ratios by calculating the highly variable featues (HVF). There are three implemented

visium_giotto_object <- calculateHVF(gobject = visium_giotto_object, 
                             method = "cov_groups",
                             save_plot = TRUE)
return_plot = TRUE and return_gobject = TRUE 

          plot will not be returned to object, but can still be saved with save_plot = TRUE or manually 

# visium_giotto_object <- calculateHVF(gobject = visium_giotto_object,
#                              method = "cov_loess",
#                              save_plot = TRUE)
# visium_giotto_object <- calculateHVF(gobject = visium_giotto_object,
#                              method = "var_p_resid",
#                              save_plot = TRUE)

# PCA on expression values 
gene_metadata = fDataDT(visium_giotto_object)
featgenes = gene_metadata[hvf == 'yes' & perc_cells > 3 & mean_expr_det > 0.4]$feat_ID

## run PCA on expression values (default)
visium_giotto_object <- runPCA(gobject = visium_giotto_object,
                       feats_to_use = featgenes)
a custom vector of genes will be used to subset the matrix
class of selected matrix:  dgCMatrix 
plotPCA(gobject = visium_giotto_object)

screePlot(gobject = visium_giotto_object, ncp = 30)
PCA with name:  pca  already exists and will be used for the screeplot 

dimPlot2D(gobject = visium_giotto_object,dim_reduction_to_use = "pca")

tSNE

visium_giotto_object <- runtSNE(visium_giotto_object, 
                                dimensions_to_use = 1:7)
plotTSNE(gobject = visium_giotto_object)

UMAP

visium_giotto_object <- runUMAP(visium_giotto_object, 
                        dimensions_to_use = 1:7)
                       Dim.1     Dim.2
AAACAAGTATCTCCCA-1 -2.410914  7.577038
AAACACCAATAACTGC-1  3.668974 -4.225888
plotUMAP(gobject = visium_giotto_object)

Clustering

Before clustering create a nearest network based on similar gene expression. sNN is the default algorithm can also use kNN.


visium_giotto_object <- createNearestNetwork(gobject = visium_giotto_object, 
                                     type = "sNN",
                                     dimensions_to_use = 1:10, 
                                     k = 30)

Cells can be clustered in Giotto using k-means, Leiden, or Louvain clustering.

K-means clustering

visium_giotto_object <- doKmeans(gobject = visium_giotto_object, 
                         dim_reduction_to_use = 'pca')

Leiden clustering

Increase the resolution to increase the number of clusters

visium_giotto_object <- doLeidenCluster(gobject = visium_giotto_object, 
                                resolution = 0.4, 
                                n_iterations = 1000,
                                name = "leiden_0.4_1000")

plotUMAP(gobject = visium_giotto_object,
         cell_color = 'leiden_0.4_1000', 
         show_NN_network = T, 
         point_size = 2.5)

Louvain clustering

Increase the resolution to increase the number of clusters

!! DO NOT USE: Throws an “Not a graph object” error.

```r
# visium_giotto_object <- doLouvainCluster(gobject = visium_giotto_object, 
#                                 resolution = 0.4, 
#                                 version = \community\,
#                                 name = \louvain_clus\)
# 
# plotUMAP(gobject = visium_giotto_object,
#          cell_color = 'leiden_0.4_1000', 
#          show_NN_network = T, 
#          point_size = 2.5)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->


Clusters of interest can be further sub-clustered. Choose the clusters to be sub-clustered with the selected_clusters argument.

WARNING: Takes a long time!!!ß

<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuIyMgTGVpZGVuIHN1YmNsdXN0ZXJpbmcgZm9yIHNwZWNpZmllZCBjbHVzdGVyc1xuIyB2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBkb0xlaWRlblN1YkNsdXN0ZXIoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LFxuIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1uID0gJ2xlaWRlbl8wLjRfMTAwMCcsXG4jICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x1dGlvbiA9IDAuMixcbiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrX25laWdoYm9ycyA9IDEwLFxuIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh2Zl9wYXJhbSA9IGxpc3QobWV0aG9kID0gJ2Nvdl9sb2VzcycsXG4jICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaWZmZXJlbmNlX2luX2NvdiA9IDAuMSksXG4jICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcGNhX3BhcmFtID0gbGlzdChleHByZXNzaW9uX3ZhbHVlcyA9ICdub3JtYWxpemVkJyxcbiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3VuaXQgPSBGLFxuIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2VudGVyID0gRiksXG4jICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm5fcGFyYW0gPSBsaXN0KGRpbWVuc2lvbnNfdG9fdXNlID0gMTo1KSxcbiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZF9jbHVzdGVycyA9IGMoNSwgNiwgNyksXG4jICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICdzdWJfbGVpZGVuX2NsdXNfc2VsZWN0JylcblxuI1Bsb3QgYSBVTUFQIHRvIHZpc3VhbGl6ZSBzdWItY2x1c3RlcnNcbiMgcGxvdFVNQVAoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCBjZWxsX2NvbG9yID0gJ3N1Yl9sZWlkZW5fY2x1c19zZWxlY3QnLCBzaG93X05OX25ldHdvcmsgPSBUKVxuYGBgXG5gYGAifQ== -->

```r
```r
## Leiden subclustering for specified clusters
# visium_giotto_object <- doLeidenSubCluster(gobject = visium_giotto_object,
#                              cluster_column = 'leiden_0.4_1000',
#                              resolution = 0.2,
#                              k_neighbors = 10,
#                              hvf_param = list(method = 'cov_loess',
#                                               difference_in_cov = 0.1),
#                              pca_param = list(expression_values = 'normalized',
#                                               scale_unit = F,
#                                               center = F),
#                              nn_param = list(dimensions_to_use = 1:5),
#                              selected_clusters = c(5, 6, 7),
#                              name = 'sub_leiden_clus_select')

#Plot a UMAP to visualize sub-clusters
# plotUMAP(gobject = visium_giotto_object, cell_color = 'sub_leiden_clus_select', show_NN_network = T)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->




# Differentially expressed genes
Now we have clustered the cells, we need to find differentially expressed genes between the identified named clusters, in this case Leiden clusters.
**method** - Method to use fror the the detection of differentially expressed features, can select "scran", "gini" or "mast".
**expression_values** - Feature expession values to use, select either "normalized", "scaled" or "custom".


<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuU1Rfc2NyYW5fbWFya2Vyc19zdWJjbHVzdGVycyA8LSBmaW5kTWFya2Vyc19vbmVfdnNfYWxsKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSBcInNjcmFuXCIsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHByZXNzaW9uX3ZhbHVlcyA9XCJub3JtYWxpemVkXCIsIFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2x1c3Rlcl9jb2x1bW4gPSBcImxlaWRlbl8wLjRfMTAwMFwiKVxuYGBgIn0= -->

```r
ST_scran_markers_subclusters <- findMarkers_one_vs_all(gobject = visium_giotto_object, 
                                                      method = "scran",
                                                      expression_values ="normalized", 
                                                      cluster_column = "leiden_0.4_1000")
using 'Scran' to detect marker feats. If used in published research, please cite:
  Lun ATL, McCarthy DJ, Marioni JC (2016).
  'A step-by-step workflow for low-level analysis of single-cell RNA-seq data with Bioconductor.'
  F1000Res., 5, 2122. doi: 10.12688/f1000research.9501.2. 

  |                                                                                                               
  |                                                                                                         |   0%
                                                                                                                  

 start with cluster  1 

  |                                                                                                               
  |                                                                                                         |   0%
  |                                                                                                               
  |============                                                                                             |  11%
                                                                                                                  

 start with cluster  2 

  |                                                                                                               
  |============                                                                                             |  11%
  |                                                                                                               
  |=======================                                                                                  |  22%
                                                                                                                  

 start with cluster  3 

  |                                                                                                               
  |=======================                                                                                  |  22%
  |                                                                                                               
  |===================================                                                                      |  33%
                                                                                                                  

 start with cluster  4 

  |                                                                                                               
  |===================================                                                                      |  33%
  |                                                                                                               
  |===============================================                                                          |  44%
                                                                                                                  

 start with cluster  5 

  |                                                                                                               
  |===============================================                                                          |  44%
  |                                                                                                               
  |==========================================================                                               |  56%
                                                                                                                  

 start with cluster  6 

  |                                                                                                               
  |==========================================================                                               |  56%
  |                                                                                                               
  |======================================================================                                   |  67%
                                                                                                                  

 start with cluster  7 

  |                                                                                                               
  |======================================================================                                   |  67%
  |                                                                                                               
  |==================================================================================                       |  78%
                                                                                                                  

 start with cluster  8 

  |                                                                                                               
  |==================================================================================                       |  78%
  |                                                                                                               
  |=============================================================================================            |  89%
                                                                                                                  

 start with cluster  9 

  |                                                                                                               
  |=============================================================================================            |  89%
  |                                                                                                               
  |=========================================================================================================| 100%
                                                                                                                  

Correlation between top selected marker genes and identified clusters

ST_top5genes <- ST_scran_markers_subclusters[, head(.SD, 3),by = "cluster"]$feats 

plotMetaDataHeatmap(gobject = visium_giotto_object,
                    selected_feats = ST_top5genes,
                    metadata_cols = c("leiden_0.4_1000"))

Spatial dimension plot

# spatial and dimension plots
spatial_dim_plot <-spatDimPlot(gobject = visium_giotto_object, 
                               cell_color = 'leiden_0.4_1000',
                               dim_point_size = 2, 
                               spat_point_size = 2.5)


spatial_dim_plot 

spatDimPlot(gobject = visium_giotto_object, 
            cell_color = 'nr_feats', 
            color_as_factor = F,
            dim_point_size = 2, 
            spat_point_size = 2.5)

# dimension plots grouped by cluster
spatPlot2D(visium_giotto_object, 
           cell_color = 'leiden_0.4_1000',
           coord_fix_ratio = 1)

spatPlot2D(visium_giotto_object, 
           cell_color = 'leiden_0.4_1000',
           group_by = 'leiden_0.4_1000', 
           coord_fix_ratio = 1,
           cow_n_col = 6, 
           show_legend = F,
           save_param = list(base_width = 14, 
                             base_height = 14))

spatPlot2D(visium_giotto_object, cell_color = 'leiden_0.4_1000',
           select_cell_groups = c('8','4'), coord_fix_ratio = 1, show_other_cells = TRUE,
           cell_color_code = c( "8" = "red","4" = "green4"), other_cell_color = "grey", other_point_size = 1.5,
           save_param = list(base_width = 7, base_height = 7))

# create and show subset, use the coordiantes from plot above
DG_subset = subsetGiottoLocs(visium_giotto_object,
                             x_max = 1000, x_min = 500,
                             y_max = -800, y_min = -1200,
                             return_gobject = TRUE)

spatDimPlot(gobject = DG_subset, cell_color = "leiden_0.4_1000", spat_point_size = 5)

Marker Gene Detection

Gini markers - Jiang, L., Chen, H., Pinello, L. et al. GiniClust: detecting rare cell types from single-cell gene expression data with Gini index. Genome Biol 17, 144 (2016). https://doi.org/10.1186/s13059-016-1010-4

gini_markers_subclusters = findMarkers_one_vs_all(gobject = visium_giotto_object,
                                                  method = 'gini',
                                                  expression_values = 'normalized',
                                                  cluster_column = 'leiden_0.4_1000',
                                                  min_feats = 20,
                                                  min_expr_gini_score = 0.5,
                                                  min_det_gini_score = 0.5)

  |                                                                                                               
  |                                                                                                         |   0%
                                                                                                                  

 start with cluster  1 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |                                                                                                         |   0%
  |                                                                                                               
  |============                                                                                             |  11%
                                                                                                                  

 start with cluster  2 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |============                                                                                             |  11%
  |                                                                                                               
  |=======================                                                                                  |  22%
                                                                                                                  

 start with cluster  3 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |=======================                                                                                  |  22%
  |                                                                                                               
  |===================================                                                                      |  33%
                                                                                                                  

 start with cluster  4 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |===================================                                                                      |  33%
  |                                                                                                               
  |===============================================                                                          |  44%
                                                                                                                  

 start with cluster  5 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |===============================================                                                          |  44%
  |                                                                                                               
  |==========================================================                                               |  56%
                                                                                                                  

 start with cluster  6 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |==========================================================                                               |  56%
  |                                                                                                               
  |======================================================================                                   |  67%
                                                                                                                  

 start with cluster  7 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |======================================================================                                   |  67%
  |                                                                                                               
  |==================================================================================                       |  78%
                                                                                                                  

 start with cluster  8 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |==================================================================================                       |  78%
  |                                                                                                               
  |=============================================================================================            |  89%
                                                                                                                  

 start with cluster  9 
completed 1: preparation 
completed 2: subset expression data 
completed 3: subset spatial locations 
completed 4: subset cell (spatial units) and feature IDs 
completed 5: subset cell metadata 
completed 6: subset feature metadata 
completed 7: subset spatial network(s) 
completed 8: subsetted dimension reductions 
completed 9: subsetted nearest network(s) 
completed 10: subsetted spatial enrichment results 
number of frames:  9 
sys parent:  8 

  |                                                                                                               
  |=============================================================================================            |  89%
  |                                                                                                               
  |=========================================================================================================| 100%
                                                                                                                  
topgenes_gini = gini_markers_subclusters[, head(.SD, 2), by = 'cluster']$feats

# violinplot
violinPlot(visium_giotto_object, feats = unique(topgenes_gini), cluster_column = 'leiden_0.4_1000',
           strip_text = 8, strip_position = 'right',
           save_param = list(base_width = 5, base_height = 20))

# cluster heatmap
plotMetaDataHeatmap(visium_giotto_object, selected_feats = unique(topgenes_gini),
                    metadata_cols = c('leiden_0.4_1000'),
                    x_text_size = 10, y_text_size = 10)

# umap plots
dimFeatPlot2D(visium_giotto_object, expression_values = 'scaled',
              feats = gini_markers_subclusters[, head(.SD, 1), by = 'cluster']$feats,
              cow_n_col = 4, point_size = 0.75,
              save_param = list(base_width = 8, base_height = 8))

Scran marker detection

# Scran Markers
scran_markers_subclusters = findMarkers_one_vs_all(gobject = visium_giotto_object,
                                                   method = 'scran',
                                                   expression_values = 'normalized',
                                                   cluster_column = 'leiden_0.4_1000')
using 'Scran' to detect marker feats. If used in published research, please cite:
  Lun ATL, McCarthy DJ, Marioni JC (2016).
  'A step-by-step workflow for low-level analysis of single-cell RNA-seq data with Bioconductor.'
  F1000Res., 5, 2122. doi: 10.12688/f1000research.9501.2. 

  |                                                                                                               
  |                                                                                                         |   0%
                                                                                                                  

 start with cluster  1 

  |                                                                                                               
  |                                                                                                         |   0%
  |                                                                                                               
  |============                                                                                             |  11%
                                                                                                                  

 start with cluster  2 

  |                                                                                                               
  |============                                                                                             |  11%
  |                                                                                                               
  |=======================                                                                                  |  22%
                                                                                                                  

 start with cluster  3 

  |                                                                                                               
  |=======================                                                                                  |  22%
  |                                                                                                               
  |===================================                                                                      |  33%
                                                                                                                  

 start with cluster  4 

  |                                                                                                               
  |===================================                                                                      |  33%
  |                                                                                                               
  |===============================================                                                          |  44%
                                                                                                                  

 start with cluster  5 

  |                                                                                                               
  |===============================================                                                          |  44%
  |                                                                                                               
  |==========================================================                                               |  56%
                                                                                                                  

 start with cluster  6 

  |                                                                                                               
  |==========================================================                                               |  56%
  |                                                                                                               
  |======================================================================                                   |  67%
                                                                                                                  

 start with cluster  7 

  |                                                                                                               
  |======================================================================                                   |  67%
  |                                                                                                               
  |==================================================================================                       |  78%
                                                                                                                  

 start with cluster  8 

  |                                                                                                               
  |==================================================================================                       |  78%
  |                                                                                                               
  |=============================================================================================            |  89%
                                                                                                                  

 start with cluster  9 

  |                                                                                                               
  |=============================================================================================            |  89%
  |                                                                                                               
  |=========================================================================================================| 100%
                                                                                                                  
topgenes_scran = scran_markers_subclusters[, head(.SD, 2), by = 'cluster']$feats

# violinplot
violinPlot(visium_giotto_object, feats = unique(topgenes_scran), cluster_column = 'leiden_0.4_1000',
           strip_text = 10, strip_position = 'right',
           save_param = list(base_width = 5, base_height = 20))

# cluster heatmap
plotMetaDataHeatmap(visium_giotto_object, selected_feats = topgenes_scran,
                    metadata_cols = c('leiden_0.4_1000'))

# umap plots
dimFeatPlot2D(visium_giotto_object, expression_values = 'scaled',
              feats = scran_markers_subclusters[, head(.SD, 1), by = 'cluster']$feats,
              cow_n_col = 3, point_size = 1,
              save_param = list(base_width = 8, base_height = 8))


pDataDT(visium_giotto_object)

Cell type annotation PAGE enrichment

Create lists of cell signature genes

```r
# Granule neurons
gran_markers <- c(\Nr3c2\, \Gabra5\, \Tubgcp2\, \Ahcyl2\,
                 \Islr2\, \Rasl10a\, \Tmem114\, \Bhlhe22\, 
                 \Ntf3\, \C1ql2\)

# Oligo dendrocytes
oligo_markers <- c(\Efhd1\, \H2-Ab1\, \Enpp6\, \Ninj2\,
                  \Bmp4\, \Tnr\, \Hapln2\, \Neu4\,
                  \Wfdc18\, \Ccp110\)        

# Di mesenchephalon
di_mesench_markers <- c(\Cartpt\, \Scn1a\, \Lypd6b\,  \Drd5\,
                       \Gpr88\, \Plcxd2\, \Cpne7\, \Pou4f1\,
                       \Ctxn2\, \Wnt4\)

# Create a binary matrix of cell signatures
signature_matrix <- makeSignMatrixPAGE(sign_names = c('Granule_neurons',
                                                     'Oligo_dendrocytes',
                                                     'di_mesenchephalon'),
                                      sign_list = list(gran_markers,
                                                       oligo_markers,
                                                       di_mesench_markers))

sign_matrix_path <- system.file(\extdata\, \sig_matrix.txt\, package = 'Giotto')

brain_sc_markers <- data.table::fread(sign_matrix_path)

sig_matrix <- as.matrix(brain_sc_markers[,-1]); rownames(sig_matrix) = brain_sc_markers$Event

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->




<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuIyBFbnJpY2htZW50IHRlc3Qgd2l0aCBQQUdFXG5cbiMgcnVuU3BhdGlhbEVucmljaCgpIGNhbiBhbHNvIGJlIHVzZWQgYXMgYSB3cmFwcGVyIGZvciBhbGwgY3VycmVudGx5IHByb3ZpZGVkIGVucmljaG1lbnQgb3B0aW9uc1xudmlzaXVtX2dpb3R0b19vYmplY3QgPSBydW5QQUdFRW5yaWNoKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgc2lnbl9tYXRyaXggPSBzaWdfbWF0cml4KVxuXG4jIGhlYXRtYXAgb2YgZW5yaWNobWVudCB2ZXJzdXMgYW5ub3RhdGlvbiAoZS5nLiBjbHVzdGVyaW5nIHJlc3VsdClcbmNlbGxfdHlwZXMgPSBjb2xuYW1lcyhzaWdfbWF0cml4KVxucGxvdE1ldGFEYXRhQ2VsbHNIZWF0bWFwKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV9jb2xzID0gJ2xlaWRlbl9jbHVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZV9jb2xzID0gY2VsbF90eXBlcyxcbiAgICAgICAgICAgICAgICAgICAgICAgICBzcGF0X2Vucl9uYW1lcyA9ICdQQUdFJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICB4X3RleHRfc2l6ZSA9IDgsIFxuICAgICAgICAgICAgICAgICAgICAgICAgIHlfdGV4dF9zaXplID0gOCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBzYXZlX3BhcmFtID0gbGlzdChzYXZlX25hbWU9XFw3X2FfbWV0YWhlYXRtYXBcXCkpXG5gYGBcbmBgYCJ9 -->

```r
```r
# Enrichment test with PAGE

# runSpatialEnrich() can also be used as a wrapper for all currently provided enrichment options
visium_giotto_object = runPAGEEnrich(gobject = visium_giotto_object, sign_matrix = sig_matrix)

# heatmap of enrichment versus annotation (e.g. clustering result)
cell_types = colnames(sig_matrix)
plotMetaDataCellsHeatmap(gobject = visium_giotto_object,
                         metadata_cols = 'leiden_clus',
                         value_cols = cell_types,
                         spat_enr_names = 'PAGE',
                         x_text_size = 8, 
                         y_text_size = 8,
                         save_param = list(save_name=\7_a_metaheatmap\))

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuIyBWaXN1YWxpemF0aW9uc1xuY2VsbF90eXBlc19zdWJzZXQgPSBjb2xuYW1lcyhzaWdfbWF0cml4KVsxOjEwXVxuc3BhdENlbGxQbG90KGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgXG4gICAgICAgICAgICAgc3BhdF9lbnJfbmFtZXMgPSAnUEFHRScsXG4gICAgICAgICAgICAgY2VsbF9hbm5vdGF0aW9uX3ZhbHVlcyA9IGNlbGxfdHlwZXNfc3Vic2V0LFxuICAgICAgICAgICAgIGNvd19uX2NvbCA9IDQsY29vcmRfZml4X3JhdGlvID0gTlVMTCwgcG9pbnRfc2l6ZSA9IDAuNzUsXG4gICAgICAgICAgICAgc2F2ZV9wYXJhbSA9IGxpc3Qoc2F2ZV9uYW1lPVxcN19iX3NwYXRjZWxscGxvdF8xXFwpKVxuYGBgXG5gYGAifQ== -->

```r
```r
# Visualizations
cell_types_subset = colnames(sig_matrix)[1:10]
spatCellPlot(gobject = visium_giotto_object, 
             spat_enr_names = 'PAGE',
             cell_annotation_values = cell_types_subset,
             cow_n_col = 4,coord_fix_ratio = NULL, point_size = 0.75,
             save_param = list(save_name=\7_b_spatcellplot_1\))

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuY2VsbF90eXBlc19zdWJzZXQgPSBjb2xuYW1lcyhzaWdfbWF0cml4KVsxMToyMF1cbnNwYXRDZWxsUGxvdChnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsIHNwYXRfZW5yX25hbWVzID0gJ1BBR0UnLCBcbiAgICAgICAgICAgICBjZWxsX2Fubm90YXRpb25fdmFsdWVzID0gY2VsbF90eXBlc19zdWJzZXQsIGNvd19uX2NvbCA9IDQsXG4gICAgICAgICAgICAgY29vcmRfZml4X3JhdGlvID0gTlVMTCwgcG9pbnRfc2l6ZSA9IDAuNzUsIFxuICAgICAgICAgICAgIHNhdmVfcGFyYW0gPSBsaXN0KHNhdmVfbmFtZT1cXDdfY19zcGF0Y2VsbHBsb3RfMlxcKSlcbmBgYFxuYGBgIn0= -->

```r
```r
cell_types_subset = colnames(sig_matrix)[11:20]
spatCellPlot(gobject = visium_giotto_object, spat_enr_names = 'PAGE', 
             cell_annotation_values = cell_types_subset, cow_n_col = 4,
             coord_fix_ratio = NULL, point_size = 0.75, 
             save_param = list(save_name=\7_c_spatcellplot_2\))

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->




<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuIyBkb3dubG9hZCBkYXRhIHRvIHJlc3VsdHMgZGlyZWN0b3J5ICMjIyNcbiMgaWYgd2dldCBpcyBpbnN0YWxsZWQsIHNldCBtZXRob2QgPSAnd2dldCdcbiMgaWYgeW91IHJ1biBpbnRvIGF1dGhlbnRpY2F0aW9uIGlzc3VlcyB3aXRoIHdnZXQsIHRoZW4gYWRkIFxcIGV4dHJhID0gJy0tbm8tY2hlY2stY2VydGlmaWNhdGUnIFxcXG5cbmdldFNwYXRpYWxEYXRhc2V0KGRhdGFzZXQgPSAnc2NSTkFfbW91c2VfYnJhaW4nLCBkaXJlY3RvcnkgPSByZXN1bHRzX2ZvbGRlcilcblxuc2NfZXhwcmVzc2lvbiA8LSBwYXN0ZTAocmVzdWx0c19mb2xkZXIsIFxcL2JyYWluX3NjX2V4cHJlc3Npb25fbWF0cml4LnR4dC5nelxcKVxuc2NfbWV0YWRhdGEgPC0gcGFzdGUwKHJlc3VsdHNfZm9sZGVyLFxcL2JyYWluX3NjX21ldGFkYXRhLmNzdlxcKVxuXG5naW90dG9fU0MgPC0gY3JlYXRlR2lvdHRvT2JqZWN0KFxuICBleHByZXNzaW9uID0gc2NfZXhwcmVzc2lvbixcbiAgaW5zdHJ1Y3Rpb25zID0gaW5zdHJzXG4pXG5cbmdpb3R0b19TQyA8LSBhZGRDZWxsTWV0YWRhdGEoZ2lvdHRvX1NDLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdfbWV0YWRhdGEgPSBkYXRhLnRhYmxlOjpmcmVhZChzY19tZXRhZGF0YSkpXG5cbmdpb3R0b19TQyA8LSBub3JtYWxpemVHaW90dG8oZ2lvdHRvX1NDKVxuYGBgXG5gYGAifQ== -->

```r
```r
# download data to results directory ####
# if wget is installed, set method = 'wget'
# if you run into authentication issues with wget, then add \ extra = '--no-check-certificate' \

getSpatialDataset(dataset = 'scRNA_mouse_brain', directory = results_folder)

sc_expression <- paste0(results_folder, \/brain_sc_expression_matrix.txt.gz\)
sc_metadata <- paste0(results_folder,\/brain_sc_metadata.csv\)

giotto_SC <- createGiottoObject(
  expression = sc_expression,
  instructions = instrs
)

giotto_SC <- addCellMetadata(giotto_SC,
                             new_metadata = data.table::fread(sc_metadata))

giotto_SC <- normalizeGiotto(giotto_SC)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuIyAxLjIgW3Nob3J0Y3V0XSBmdWxseSBwcmUtcHJlcGFyZWQgbWF0cml4IGZvciBhbGwgY2VsbCB0eXBlc1xuc2lnbl9tYXRyaXhfcGF0aCA9IHN5c3RlbS5maWxlKFxcZXh0ZGF0YVxcLCBcXHNpZ19tYXRyaXgudHh0XFwsIHBhY2thZ2UgPSAnR2lvdHRvJylcbmJyYWluX3NjX21hcmtlcnMgPSBkYXRhLnRhYmxlOjpmcmVhZChzaWduX21hdHJpeF9wYXRoKVxuUEFHRV9tYXRyaXhfMiA9IGFzLm1hdHJpeChicmFpbl9zY19tYXJrZXJzWywtMV0pXG5yb3duYW1lcyhQQUdFX21hdHJpeF8yKSA9IGJyYWluX3NjX21hcmtlcnMkRXZlbnRcblxuXG4jIC0tLVxuXG4jIE1ha2UgUEFHRSBtYXRyaXggZnJvbSBzaW5nbGUgY2VsbCBkYXRhc2V0XG5tYXJrZXJzX3NjcmFuID0gZmluZE1hcmtlcnNfb25lX3ZzX2FsbChnb2JqZWN0PWdpb3R0b19TQywgbWV0aG9kPVxcc2NyYW5cXCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25fdmFsdWVzPVxcbm9ybWFsaXplZFxcLCBjbHVzdGVyX2NvbHVtbiA9IFxcQ2xhc3NcXCwgbWluX2ZlYXRzPTMpXG50b3BfbWFya2VycyA8LSBtYXJrZXJzX3NjcmFuWywgaGVhZCguU0QsIDEwKSwgYnk9XFxjbHVzdGVyXFxdXG5jZWxsdHlwZXM8LWxldmVscyhmYWN0b3IobWFya2Vyc19zY3JhbiRjbHVzdGVyKSlcbnNpZ25fbGlzdDwtbGlzdCgpXG5mb3IgKGkgaW4gMTpsZW5ndGgoY2VsbHR5cGVzKSl7XG4gIHNpZ25fbGlzdFtbaV1dPC10b3BfbWFya2Vyc1t3aGljaCh0b3BfbWFya2VycyRjbHVzdGVyID09IGNlbGx0eXBlc1tpXSksXSRmZWF0c1xufVxuXG5QQUdFX21hdHJpeF8zID0gbWFrZVNpZ25NYXRyaXhQQUdFKHNpZ25fbmFtZXMgPSBjZWxsdHlwZXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNpZ25fbGlzdCA9IHNpZ25fbGlzdClcblxuIyBFbnJpY2htZW50IHRlc3Qgd2l0aCBQQUdFXG5cbiMgcnVuU3BhdGlhbEVucmljaCgpIGNhbiBhbHNvIGJlIHVzZWQgYXMgYSB3cmFwcGVyIGZvciBhbGwgY3VycmVudGx5IHByb3ZpZGVkIGVucmljaG1lbnQgb3B0aW9uc1xudmlzaXVtX2dpb3R0b19vYmplY3QgPSBydW5QQUdFRW5yaWNoKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgc2lnbl9tYXRyaXggPSBQQUdFX21hdHJpeF8yKVxuXG4jIDEuNSBoZWF0bWFwIG9mIGVucmljaG1lbnQgdmVyc3VzIGFubm90YXRpb24gKGUuZy4gY2x1c3RlcmluZyByZXN1bHQpXG5jZWxsX3R5cGVzX1BBR0UgPSBjb2xuYW1lcyhQQUdFX21hdHJpeF8yKVxucGxvdE1ldGFEYXRhQ2VsbHNIZWF0bWFwKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV9jb2xzID0gJ2xlaWRlbl9jbHVzJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZV9jb2xzID0gY2VsbF90eXBlc19QQUdFLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHNwYXRfZW5yX25hbWVzID0gJ1BBR0UnLFxuICAgICAgICAgICAgICAgICAgICAgICAgIHhfdGV4dF9zaXplID0gOCxcbiAgICAgICAgICAgICAgICAgICAgICAgICB5X3RleHRfc2l6ZSA9IDgpXG5gYGBcbmBgYCJ9 -->

```r
```r
# 1.2 [shortcut] fully pre-prepared matrix for all cell types
sign_matrix_path = system.file(\extdata\, \sig_matrix.txt\, package = 'Giotto')
brain_sc_markers = data.table::fread(sign_matrix_path)
PAGE_matrix_2 = as.matrix(brain_sc_markers[,-1])
rownames(PAGE_matrix_2) = brain_sc_markers$Event


# ---

# Make PAGE matrix from single cell dataset
markers_scran = findMarkers_one_vs_all(gobject=giotto_SC, method=\scran\,
                                       expression_values=\normalized\, cluster_column = \Class\, min_feats=3)
top_markers <- markers_scran[, head(.SD, 10), by=\cluster\]
celltypes<-levels(factor(markers_scran$cluster))
sign_list<-list()
for (i in 1:length(celltypes)){
  sign_list[[i]]<-top_markers[which(top_markers$cluster == celltypes[i]),]$feats
}

PAGE_matrix_3 = makeSignMatrixPAGE(sign_names = celltypes,
                                   sign_list = sign_list)

# Enrichment test with PAGE

# runSpatialEnrich() can also be used as a wrapper for all currently provided enrichment options
visium_giotto_object = runPAGEEnrich(gobject = visium_giotto_object, sign_matrix = PAGE_matrix_2)

# 1.5 heatmap of enrichment versus annotation (e.g. clustering result)
cell_types_PAGE = colnames(PAGE_matrix_2)
plotMetaDataCellsHeatmap(gobject = visium_giotto_object,
                         metadata_cols = 'leiden_clus',
                         value_cols = cell_types_PAGE,
                         spat_enr_names = 'PAGE',
                         x_text_size = 8,
                         y_text_size = 8)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuIyBWaXN1YWxpemF0aW9uc1xuc3BhdENlbGxQbG90MkQoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LFxuICAgICAgICAgICAgICAgc3BhdF9lbnJfbmFtZXMgPSAnUEFHRScsXG4gICAgICAgICAgICAgICBjZWxsX2Fubm90YXRpb25fdmFsdWVzID0gY2VsbF90eXBlc19QQUdFWzE6Ml0sXG4gICAgICAgICAgICAgICBjb3dfbl9jb2wgPSAyLGNvb3JkX2ZpeF9yYXRpbyA9IDEsIHBvaW50X3NpemUgPSAxLjI1LCBzaG93X2xlZ2VuZCA9IFQpXG5gYGBcbmBgYCJ9 -->

```r
```r
# Visualizations
spatCellPlot2D(gobject = visium_giotto_object,
               spat_enr_names = 'PAGE',
               cell_annotation_values = cell_types_PAGE[1:2],
               cow_n_col = 2,coord_fix_ratio = 1, point_size = 1.25, show_legend = T)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuc3BhdERpbUNlbGxQbG90MkQoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LFxuICAgICAgICAgICAgICAgICAgc3BhdF9lbnJfbmFtZXMgPSAnUEFHRScsXG4gICAgICAgICAgICAgICAgICBjZWxsX2Fubm90YXRpb25fdmFsdWVzID0gY2VsbF90eXBlc19QQUdFWzE6Ml0sXG4gICAgICAgICAgICAgICAgICBjb3dfbl9jb2wgPSAxLCBzcGF0X3BvaW50X3NpemUgPSAxLFxuICAgICAgICAgICAgICAgICAgcGxvdF9hbGlnbm1lbnQgPSAnaG9yaXpvbnRhbCcsXG4gICAgICAgICAgICAgICAgICBzYXZlX3BhcmFtID0gbGlzdChiYXNlX3dpZHRoPTcsIGJhc2VfaGVpZ2h0PTEwKSlcbmBgYFxuYGBgIn0= -->

```r
```r
spatDimCellPlot2D(gobject = visium_giotto_object,
                  spat_enr_names = 'PAGE',
                  cell_annotation_values = cell_types_PAGE[1:2],
                  cow_n_col = 1, spat_point_size = 1,
                  plot_alignment = 'horizontal',
                  save_param = list(base_width=7, base_height=10))

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->



<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuUkRhdGEubmFtZSA8LSBcXGdpb3R0b19zcGF0aWFsX3RyYW5zY3JpcHRvbWljc1xcXG5zYXZlLmltYWdlKFJEYXRhLm5hbWUpXG5gYGBcbmBgYCJ9 -->

```r
```r
RData.name <- \giotto_spatial_transcriptomics\
save.image(RData.name)

<!-- rnb-source-end -->

<!-- rnb-chunk-end -->


<!-- rnb-text-begin -->




<!-- rnb-text-end -->


<!-- rnb-chunk-begin -->


<!-- rnb-source-begin eyJkYXRhIjoiYGBgclxuYGBgclxuc2Vzc2lvbkluZm8oKVxuYGBgXG5gYGAifQ== -->

```r
```r
sessionInfo()

```

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKSW5zdGFsbCBHaW90dG8sIEdpb3R0b0RhdGEgYW5kIHRoZSBHaW90dG8gZW52aXJvbm1tZW50CmBgYHtyIExvYWQgcmVxdWlyZWQgbGlicmFyaWVzfQppZighIkdpb3R0byIgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSkgewogIGRldnRvb2xzOjppbnN0YWxsX2dpdGh1YigiZHJpZXNsYWIvR2lvdHRvQHN1aXRlIiwgZm9yY2UgPSBUUlVFKQp9CmxpYnJhcnkoIkdpb3R0byIpCgppZighIkdpb3R0b0RhdGEiICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpIHsKICByZW1vdGVzOjppbnN0YWxsX2dpdGh1YigiZHJpZXNsYWIvR2lvdHRvRGF0YSIpCn0KbGlicmFyeShHaW90dG9EYXRhKQoKZ2Vudl9leGlzdHMgPC0gY2hlY2tHaW90dG9FbnZpcm9ubWVudCgpCmlmKCFnZW52X2V4aXN0cyl7CiAgIyBUaGUgZm9sbG93aW5nIGNvbW1hbmQgbmVlZCBvbmx5IGJlIHJ1biBvbmNlIHRvIGluc3RhbGwgdGhlIEdpb3R0byBlbnZpcm9ubWVudC4KICBpbnN0YWxsR2lvdHRvRW52aXJvbm1lbnQoZm9yY2VfZW52aXJvbm1lbnQgPSBUUlVFKQogIAojIGxpYnJhcnkoInRpZHl2ZXJzZSIpCn0KYGBgCgojIyBDcmVhdGUgdGhlIEdpb3R0byBvYmplY3QKCmBgYHtyIFNldCB1cCB3b3JrIHNwYWNlfQpyZXN1bHRzX2ZvbGRlciA9ICJHaW90dG9fUmVzdWx0cyIKCmluc3RycyA9IGNyZWF0ZUdpb3R0b0luc3RydWN0aW9ucyhzYXZlX2RpciA9IHJlc3VsdHNfZm9sZGVyLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZV9wbG90ID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcGxvdCA9IFRSVUUpCmBgYAoKYGBge3IgY3JlYXRlIEdpb3R0byBvYmplY3R9CiMjIHByb3ZpZGUgcGF0aCB0byB2aXNpdW0gZm9sZGVyCmRhdGFfcGF0aDwtICIvVXNlcnMvZ3JhaGFtL0RvY3VtZW50cy9Qb2x5b21pY3MvUHIyMDI5L3J1bjEvRDEvb3V0cy8iCgojIyBkaXJlY3RseSBmcm9tIHZpc2l1bSBmb2xkZXIKdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gY3JlYXRlR2lvdHRvVmlzaXVtT2JqZWN0KHZpc2l1bV9kaXIgPSBkYXRhX3BhdGgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHByX2RhdGEgPSAncmF3JywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBuZ19uYW1lID0gJ3Rpc3N1ZV9sb3dyZXNfaW1hZ2UucG5nJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdlbmVfY29sdW1uX2luZGV4ID0gMiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluc3RydWN0aW9ucyA9IGluc3RycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvX21hbnVhbF9hZGogPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1heF9hZGogPSAyNDgsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4bWluX2FkaiA9IDM2NSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHltYXhfYWRqID0gNDYwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeW1pbl9hZGogPSAyMDApCgojIFNob3cgaW1hZ2VzIGFzc29jaWF0ZWQgd2l0aCBHaW90dG8gb2JqZWN0CnNob3dHaW90dG9JbWFnZU5hbWVzKHZpc2l1bV9naW90dG9fb2JqZWN0KQoKIyBDaGVjayBtZXRhZGF0YQpwRGF0YURUKHZpc2l1bV9naW90dG9fb2JqZWN0KQoKIyMgc2hvdyBwbG90CnNsaWRlX2ltYWdlIDwtIHNwYXRQbG90MkQoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsX2NvbG9yID0gJ2luX3Rpc3N1ZScsCiAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRfc2l6ZSA9IDIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2VsbF9jb2xvcl9jb2RlID0gYygnMCcgPSAnbGlnaHRncmV5JywgJzEnID0gJ2JsdWUnKSwKICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2ltYWdlID0gVCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgaW1hZ2VfbmFtZSA9ICdpbWFnZScpCgpzbGlkZV9pbWFnZQpgYGAKCiMgUHJvY2VzcyBHaW90dG8gVmlzaXVtIG9iamVjdAojIyBGaWx0ZXIKRmlsdGVycyBhcmUgYmFzZWQgb246CioqZXhwcmVzc2lvbl90aHJlc2hvbGQqKiAtIHNldCB0aGUgbWluaW11bSBleHByZXNzaW9uIGxldmVsCioqZmVhdF9kZXRfaW5fbWluX2NlbGxzKiogLSBzZXQgdGhlIG1pbmltdW0gbnVtYmVyIG9mIGNlbGxzIHRoYXQgZXhwcmVzc2VzIGEgZmVhdHVyZS9nZW5lCioqbWluX2RldF9mZWF0c19wZXJfY2VsbCoqIC0gc2V0IHRoZSBtaW5pbXVtIG51bWJlciBvZiBmZWF0dXJlcy9nZW5lcyBleHByZXNzZWQgcGVyIGNlbGwKCgpgYGB7ciBjZWxsIGRpc3RyaWJ1dGlvbn0KZmlsdGVyRGlzdHJpYnV0aW9ucyh2aXNpdW1fZ2lvdHRvX29iamVjdCwgZGV0ZWN0aW9uID0gJ2NlbGxzJykKYGBgCgpgYGB7ciBmZWF0dXJlIGRpc3RyaWJ1dGlvbn0KZmlsdGVyRGlzdHJpYnV0aW9ucyh2aXNpdW1fZ2lvdHRvX29iamVjdCwgZGV0ZWN0aW9uID0gJ2ZlYXRzJykKYGBgClRoaXMgaXMgYSB2aXN1YWxpc2F0aW9uIHNob3dpbmcgdGhlIG51bWJlciBvZiBmZWF0dXJlcyBsb3N0IGJhc2VkIG9uIHRoZSB2YXJpb3VzIGZpbHRlcmluZyBwYXJhbWV0ZXJzCmBgYHtyfQpmaWx0ZXJDb21iaW5hdGlvbnMoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25fdGhyZXNob2xkcyA9IGMoMSwgMiwgMyksCiAgICAgICAgICAgICAgICAgICBmZWF0X2RldF9pbl9taW5fY2VsbHMgPSBjKDIsIDUsIDEwKSwgCiAgICAgICAgICAgICAgICAgICBtaW5fZGV0X2ZlYXRzX3Blcl9jZWxsID0gYygxMDAsIDIwMCwgNTAwKSkKYGBgCgpVc2UgdGhlIHBsb3RzIGFib3ZlIHRvIGluZm9ybSB0aGUgY3V0b2ZmIHBhcmFtZXRlcnMgZm9yIGZpbHRlckdpb3R0by4KSW4gdGhpcyBleGFtcGxlLCBhbiBleHByZXNzaW9uIHZhbHVlIG9mIDEsIGZlYXRfZGV0X2luX21pbl9jZWxscyBvZiAxMCBhbmQgbWluX2RldF9mZWF0c19wZXJfY2VsbCBvZiAyMDAuCkFsc28sIGZpbHRlciBvdXQgc3BvdCBub3QgY292ZXJlZCBieSB0aGUgdGlzc3VlLgpgYGB7ciBmaWx0ZXJ9CiMjIHN1YnNldCBvbiBzcG90cyB0aGF0IHdlcmUgY292ZXJlZCBieSB0aXNzdWUKbWV0YWRhdGEgPC0gcERhdGFEVCh2aXNpdW1fZ2lvdHRvX29iamVjdCkKaW5fdGlzc3VlX2JhcmNvZGVzIDwtIG1ldGFkYXRhW2luX3Rpc3N1ZSA9PSAxXSRjZWxsX0lECnZpc2l1bV9naW90dG9fb2JqZWN0IDwtIHN1YnNldEdpb3R0byh2aXNpdW1fZ2lvdHRvX29iamVjdCwgY2VsbF9pZHMgPSBpbl90aXNzdWVfYmFyY29kZXMpCgp2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBmaWx0ZXJHaW90dG8oZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25fdGhyZXNob2xkID0gMSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmZWF0X2RldF9pbl9taW5fY2VsbHMgPSAxMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5fZGV0X2ZlYXRzX3Blcl9jZWxsID0gMjAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25fdmFsdWVzID0gYygncmF3JyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IFQpCmBgYAoKIyMgTm9ybWFsaXplIHRoZSBleHByZXNzaW9uIG1hdHJpeApUaGVyZSBhcmUgdGhyZWUgbm9ybWFsaXNhdGlvbiBhbGdvcnl0aG1zOgoqKlN0YW5kYXJkKiogLSBOb3JtYWlsc2VzIHRoZSBkYXRhIGJ5IGxpYnJhcnkgc2l6ZSBhbmQgYSBjdXN0b20gc2NhbGUgZmFjdG9yLCB0aGVuIGxvZyB0cmFuc2Zvcm1zIGFuZCB6LXNjb3JlcyB0aGUgZGF0YSBieSBnZW5lcyBvciBjZWxscywgd2hpY2ggaXMgc3BlY2lmaWVkIGJ5IHNjYWxlX29yZGVyLiBUaGUgc2NhbGVfb3JkZXIgb3B0aW9ucyBhcmUgZmlyc3RfZmVhdHMgb3IgZmlyc3RfY2VsbHMuCmBgYHtyIG5vcm1hbGlzZSBzdGFuZGFyZH0KdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gbm9ybWFsaXplR2lvdHRvKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbm9ybV9tZXRob2RzID0gInN0YW5kYXJkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfZmVhdHMgPSBUUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlZmFjdG9yID0gNjAwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfb3JkZXIgPSAiZmlyc3RfZmVhdHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPVRSVUUpCmBgYAoKKipwZWFyc29uX3Jlc2lkKiogLSBFeHBlY3RlZCB2YWx1ZXMgY2FsY3VsYXRlZCBiYXNlZCBvbiBQZWFyc29uIGNvcnJlbGF0aW9ucywgei1zY29yZXMgYXJlIHRoZW4gY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgb2JzZXJ2ZWQgdmFsdWVzIGFuZCB0aGUgY2FsY3VsYXRlZCBleHBlY3RlZCB2YWx1ZXMuCmBgYHtyIG5vcm1hbGlzZSBwZWFyc29uLXJlc2lkfQp2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBub3JtYWxpemVHaW90dG8oZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtX21ldGhvZHMgPSAicGVhcnNvbl9yZXNpZCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX2ZlYXRzID0gVFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2FsZWZhY3RvciA9IDYwMDAsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX29yZGVyID0gImZpcnN0X2ZlYXRzIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJib3NlID1UUlVFKQpgYGAKCioqb3NtRklTSCoqIC0gVGhpcyBub3JtYWxpc2F0aW9uIG1ldGhvZCBpcyBmb3IgKmluIHNpdHUqIFJOQSBkYXRhIHVzaW5nIGEgbWV0aG9kIGRlc2NyaWJlZCBpbiBDb2RlbHVwcGkgKmV0IGFsLiogRmVhdHVyZS9nZW5lIGNvdW50cyBhcmUgbm9ybWFsaXNlZCBpbmRpdmlkdWFsbHkgYnkgdGhlIHRvdGFsIGZlYXR1cmUvZ2VuZSBjb3VudCBhbmQgdGhlbiBtdWx0aXBsaWVkIGJ5IHRoZSB0b3RhbCBudW1iZXIgb2YgZmVhdHVyZXMvZ2VuZXMuIFRoZW4sIGNlbGxzIGFyZSBpbmRpdmlkdWFsbHkgbm9ybWFsaXNlZCBieSBkaXZpZGluZyB0aGUgbm9ybWFsaXNlZCBmZWF0dXJlIGNvdW50cyBieSB0aGUgdG90YWwgZmVhdHVyZSBjb3VudHMgcGVyIGNlbGwsIHRoZW4gc2NhbGVkIGJ5IHRoZSB0b3RhbCBudW1iZXIgb2YgY2VsbHMuClRoaXMgbWV0aG9kIGlzIG5vdCBzaG93biBhcyB0aGUgZGF0YSBpcyB1bmxpa2VseSB0byBiZSBmcm9tICppbiBzaXR1KiBSTkEgZXhwZXJpbWVudHMuIEhvd2V2ZXIsIHRvIHVzZSB0aGUgYWxnb3JpdGhtIGNhbiBzcGVjaWZ5ICJvc21GSVNIIiBhcyB0aGUgYXJndW1lbnQgZm9yIG5vcm1fbWV0aG9kcy4KYGBge3Igbm9ybWFsaXNlIG9zbUZJU0h9CiMgdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gbm9ybWFsaXplR2lvdHRvKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtX21ldGhvZHMgPSAib3NtRklTSCIsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVfZmVhdHMgPSBUUlVFLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVmYWN0b3IgPSA2MDAwLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZlcmJvc2UgPVRSVUUpCmBgYAoKCiMjIEFkZCBnZW5lICYgY2VsbCBzdGF0aXN0aWNzIGFuZCBtZXRhZGF0YQpUaGUgZnVuY3Rpb24gYWRkU3RhdGlzdGljcyB3aWxsIGFkZCB0aGUgZm9sbG93aW5nIHN0YXRpc3RpY3MgdG8gY2VsbCBtZXRhZGF0YToKKipucl9mZWF0cyoqIC0gRGVub3RlcyBob3cgbWFueSBmZWF0dXJlcyBhcmUgZGV0ZWN0ZWQgcGVyIGNlbGwKKipwZXJjX2ZlYXRzKiogLSBEZW5vdGVzIHRoZSBwZXJjZW50YWdlIG9mIGZlYXR1cmVzIGRldGVjdGVkIHBlciBjZWxsCioqdG90YWxfZXhwcioqIC0gU2hvd3MgdGhlIHRvdGFsIHN1bSBvZiBmZWF0dXJlIGV4cHJlc3Npb24gcGVyIGNlbGwKCkl0IHdpbGwgYWxzbyBhZGQgdGhlIGZvbGxvd2luZyBzdGF0aXN0aWNzIHRvIGZlYXR1cmUgbWV0YWRhdGE6CioqbnJfY2VsbHMqKiAtIERlbm90ZXMgaG93IG1hbnkgY2VsbHMgaW4gd2hpY2ggdGhlIGZlYXR1cmUgaXMgZGV0ZWN0ZWQKKipwZXJfY2VsbHMqKiAtIERlbm90ZXMgdGhlIHBlcmNlbnRhZ2Ugb2YgY2VsbHMgaW4gd2hpY2ggdGhlIGZlYXR1cmUgaXMgZGV0ZWN0ZWQKKip0b3RhbF9leHByKiogLSBTaG93cyB0aGUgdG90YWwgc3VtIG9mIGZlYXR1cmUgZXhwcmVzc2lvbiBpbiBhbGwgY2VsbHMKKiptZWFuX2V4cHIqKiAtIEF2ZXJhZ2UgZmVhdHVyZSBleHByZXNzaW9uIGluIGFsbCBjZWxscwoqKm1lYW5fZXhwcl9kZXQqKiAtIEF2ZXJhZ2UgZmVhdHVyZSBleHByZXNzaW9uIGluIGNlbGxzIHdpdGggZGV0ZWN0YWJsZSBsZXZlbHMgb2YgdGhlIGZlYXR1cmUKCmBgYHtyIEFkZCBzdGF0aXN0aWNzfQp2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBhZGRTdGF0aXN0aWNzKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCkKCiMgQWNjZXNzb3JzOgpjZWxsX21ldGFkYXRhIDwtIHBEYXRhRFQodmlzaXVtX2dpb3R0b19vYmplY3QpCmZlYXR1cmVfbWV0YWRhdGEgPC0gZkRhdGFEVCh2aXNpdW1fZ2lvdHRvX29iamVjdCkKCiMgY2FsY3VsYXRlIHBlcmNlbnRhZ2Ugb2YgbWl0b2Nob25kcmlhbCBjb250ZW50IHBlciBzcG90Cm1pdG9jaG9uZHJpYWxfZ2VuZXMgPC0gZ3JlcCgnXm10LScsIHZpc2l1bV9naW90dG9fb2JqZWN0QGZlYXRfSUQkcm5hLCB2YWx1ZSA9IFQpCnZpc2l1bV9naW90dG9fb2JqZWN0IDwtIGFkZEZlYXRzUGVyYyhnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZmVhdHMgPSBtaXRvY2hvbmRyaWFsX2dlbmVzLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZWN0b3JfbmFtZSA9ICdtaXRvJykKCmBgYAoKVmlldyB0aGUgZ2VuZSBhbmQgY2VsbHMgc3RhdGlzdGljcwpgYGB7cn0KaGVhZChmRGF0YURUKHZpc2l1bV9naW90dG9fb2JqZWN0KSkgCmhlYWQocERhdGFEVCh2aXNpdW1fZ2lvdHRvX29iamVjdCkpCmBgYApWaXN1YWxpc2UgdGhlIG51bWJlciBvZiBmZWF0dXJlcy9nZW5lcyBhbmQgbWl0b2Nob25kcmlhbCBnZW5lcyBwZXIgY2VsbAoKYGBge3J9CgojIFZpc3VhbGl6ZSBudW1iZXIgb2YgZ2VuZXMgYW5kIG1pdG9jaG9uZHJpYWwgY29udGVudCBwZXIgc3BvdApzcGF0UGxvdDJEKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwKICAgICAgICAgICBzaG93X2ltYWdlID0gVFJVRSwKICAgICAgICAgICBwb2ludF9hbHBoYSA9IDEsCiAgICAgICAgICAgY2VsbF9jb2xvciA9ICducl9mZWF0cycsIGNvbG9yX2FzX2ZhY3RvciA9IEYsCiAgICAgICAgICAgY29vcmRfZml4X3JhdGlvID0gMSkKCnNwYXRQbG90MkQoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICAgIHNob3dfaW1hZ2UgPSBUUlVFLAogICAgICAgICAgIHBvaW50X2FscGhhID0gMSwKICAgICAgICAgICBjZWxsX2NvbG9yID0gJ21pdG8nLCBjb2xvcl9hc19mYWN0b3IgPSBGLAogICAgICAgICAgIGNvb3JkX2ZpeF9yYXRpbyA9IDEpCmBgYAoKIyMgQWRqdXN0IGZvciB0ZWNobmljYWwgY28tZm91bmRlcnMKQWRqdXN0IGV4cHJlc3Npb24gbWF0cml4IGZvciBrbm93biBiYXRjaCBlZmZlY3RzIG9yIHRlY2hub2xvZ2ljYWwgY292YXJpYXRlcy4gSW4gdGhpcyBjYXNlIHVzZSB0aGUgbWl0b2Nob25kcmlhbCBnZW5lcyBhcyBhIGNvdmFyaWF0ZSBhbmQgcmVncmVzcyB0aGUgbnVtYmVyIG9mIGZlYXR1cmVzIGRldGVjdGVkIHBlciBjZWxsLCB0aGlzIG1lYW5zIHRoYXQgdGhlc2UgY292YXJpYXRlcyB3aWxsIG5vdCBhZmZlY3QgZnVydGhlciBhbmFseXNlcy4KYGBge3J9CnZpc2l1bV9naW90dG9fb2JqZWN0IDwtIGFkanVzdEdpb3R0b01hdHJpeChnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvdmFyaWF0ZV9jb2x1bW5zID0gYygibnJfZmVhdHMiLCAibWl0byIpLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1cGRhdGVfc2xvdCA9ICJjdXN0b20iKQpgYGAKCgoKIyBEaW1lbnNpb24gcmVkdWN0aW9uClByaW9yIHRvIHJ1bm5pbmcgY2x1c3RlciBhbmFseXNpcyBpdCBpcyBiZXN0IHRvIGRvIGZlYXR1cmUgc2VsZWN0aW9uIHRvIHJldGFpbiB0aGUgbW9zdCBpbmZvcm1hdGl2ZSBmZWF0dXJlcy9nZW5lcyB0byBvcHRpbWlzZSBzaWduYWwgdG8gbm9pc2UgcmF0aW9zIGJ5IGNhbGN1bGF0aW5nIHRoZSBoaWdobHkgdmFyaWFibGUgZmVhdHVlcyAoSFZGKS4gVGhlcmUgYXJlIHRocmVlIGltcGxlbWVudGVkIApgYGB7cn0KdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gY2FsY3VsYXRlSFZGKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gImNvdl9ncm91cHMiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmVfcGxvdCA9IFRSVUUpCiMgdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gY2FsY3VsYXRlSFZGKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1ldGhvZCA9ICJjb3ZfbG9lc3MiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2F2ZV9wbG90ID0gVFJVRSkKIyB2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBjYWxjdWxhdGVIVkYoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInZhcl9wX3Jlc2lkIiwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNhdmVfcGxvdCA9IFRSVUUpCgojIFBDQSBvbiBleHByZXNzaW9uIHZhbHVlcyAKZ2VuZV9tZXRhZGF0YSA9IGZEYXRhRFQodmlzaXVtX2dpb3R0b19vYmplY3QpCmZlYXRnZW5lcyA9IGdlbmVfbWV0YWRhdGFbaHZmID09ICd5ZXMnICYgcGVyY19jZWxscyA+IDMgJiBtZWFuX2V4cHJfZGV0ID4gMC40XSRmZWF0X0lECgojIyBydW4gUENBIG9uIGV4cHJlc3Npb24gdmFsdWVzIChkZWZhdWx0KQp2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBydW5QQ0EoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICAgICAgICAgICAgICAgIGZlYXRzX3RvX3VzZSA9IGZlYXRnZW5lcykKcGxvdFBDQShnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QpCnNjcmVlUGxvdChnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsIG5jcCA9IDMwKQpgYGAKCmBgYHtyfQpkaW1QbG90MkQoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LGRpbV9yZWR1Y3Rpb25fdG9fdXNlID0gInBjYSIpCmBgYAoKdFNORQpgYGB7cn0KdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gcnVudFNORSh2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGltZW5zaW9uc190b191c2UgPSAxOjcpCnBsb3RUU05FKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCkKYGBgCgpVTUFQCmBgYHtyfQp2aXNpdW1fZ2lvdHRvX29iamVjdCA8LSBydW5VTUFQKHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgZGltZW5zaW9uc190b191c2UgPSAxOjcpCnBsb3RVTUFQKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCkKYGBgCgoKIyBDbHVzdGVyaW5nCkJlZm9yZSBjbHVzdGVyaW5nIGNyZWF0ZSBhIG5lYXJlc3QgbmV0d29yayBiYXNlZCBvbiBzaW1pbGFyIGdlbmUgZXhwcmVzc2lvbi4gc05OIGlzIHRoZSBkZWZhdWx0IGFsZ29yaXRobSBjYW4gYWxzbyB1c2Uga05OLgpgYGB7cn0KdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gY3JlYXRlTmVhcmVzdE5ldHdvcmsoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSAic05OIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpbWVuc2lvbnNfdG9fdXNlID0gMToxMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrID0gMzApCmBgYAoKQ2VsbHMgY2FuIGJlIGNsdXN0ZXJlZCBpbiBHaW90dG8gdXNpbmcgay1tZWFucywgTGVpZGVuLCBvciBMb3V2YWluIGNsdXN0ZXJpbmcuCgojIyBLLW1lYW5zIGNsdXN0ZXJpbmcKYGBge3J9CnZpc2l1bV9naW90dG9fb2JqZWN0IDwtIGRvS21lYW5zKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBkaW1fcmVkdWN0aW9uX3RvX3VzZSA9ICdwY2EnKQpgYGAKCiMjIExlaWRlbiBjbHVzdGVyaW5nCkluY3JlYXNlIHRoZSByZXNvbHV0aW9uIHRvIGluY3JlYXNlIHRoZSBudW1iZXIgb2YgY2x1c3RlcnMKYGBge3J9CnZpc2l1bV9naW90dG9fb2JqZWN0IDwtIGRvTGVpZGVuQ2x1c3Rlcihnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdXRpb24gPSAwLjQsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5faXRlcmF0aW9ucyA9IDEwMDAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZSA9ICJsZWlkZW5fMC40XzEwMDAiKQoKcGxvdFVNQVAoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICBjZWxsX2NvbG9yID0gJ2xlaWRlbl8wLjRfMTAwMCcsIAogICAgICAgICBzaG93X05OX25ldHdvcmsgPSBULCAKICAgICAgICAgcG9pbnRfc2l6ZSA9IDIuNSkKYGBgCgojIyBMb3V2YWluIGNsdXN0ZXJpbmcKSW5jcmVhc2UgdGhlIHJlc29sdXRpb24gdG8gaW5jcmVhc2UgdGhlIG51bWJlciBvZiBjbHVzdGVycwoKISEgRE8gTk9UIFVTRTogVGhyb3dzIGFuICJOb3QgYSBncmFwaCBvYmplY3QiIGVycm9yLiAKYGBge3J9CiMgdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gZG9Mb3V2YWluQ2x1c3Rlcihnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x1dGlvbiA9IDAuNCwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2ZXJzaW9uID0gImNvbW11bml0eSIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gImxvdXZhaW5fY2x1cyIpCiMgCiMgcGxvdFVNQVAoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAojICAgICAgICAgIGNlbGxfY29sb3IgPSAnbGVpZGVuXzAuNF8xMDAwJywgCiMgICAgICAgICAgc2hvd19OTl9uZXR3b3JrID0gVCwgCiMgICAgICAgICAgcG9pbnRfc2l6ZSA9IDIuNSkKYGBgCgpDbHVzdGVycyBvZiBpbnRlcmVzdCBjYW4gYmUgZnVydGhlciBzdWItY2x1c3RlcmVkLiBDaG9vc2UgdGhlIGNsdXN0ZXJzIHRvIGJlIHN1Yi1jbHVzdGVyZWQgd2l0aCB0aGUgc2VsZWN0ZWRfY2x1c3RlcnMgYXJndW1lbnQuCgpXQVJOSU5HOiBUYWtlcyBhIGxvbmcgdGltZSEhIcOfCmBgYHtyfQojIyBMZWlkZW4gc3ViY2x1c3RlcmluZyBmb3Igc3BlY2lmaWVkIGNsdXN0ZXJzCiMgdmlzaXVtX2dpb3R0b19vYmplY3QgPC0gZG9MZWlkZW5TdWJDbHVzdGVyKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1uID0gJ2xlaWRlbl8wLjRfMTAwMCcsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHV0aW9uID0gMC4yLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAga19uZWlnaGJvcnMgPSAxMCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGh2Zl9wYXJhbSA9IGxpc3QobWV0aG9kID0gJ2Nvdl9sb2VzcycsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpZmZlcmVuY2VfaW5fY292ID0gMC4xKSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBjYV9wYXJhbSA9IGxpc3QoZXhwcmVzc2lvbl92YWx1ZXMgPSAnbm9ybWFsaXplZCcsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNjYWxlX3VuaXQgPSBGLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZW50ZXIgPSBGKSwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5uX3BhcmFtID0gbGlzdChkaW1lbnNpb25zX3RvX3VzZSA9IDE6NSksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZF9jbHVzdGVycyA9IGMoNSwgNiwgNyksCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gJ3N1Yl9sZWlkZW5fY2x1c19zZWxlY3QnKQoKI1Bsb3QgYSBVTUFQIHRvIHZpc3VhbGl6ZSBzdWItY2x1c3RlcnMKIyBwbG90VU1BUChnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsIGNlbGxfY29sb3IgPSAnc3ViX2xlaWRlbl9jbHVzX3NlbGVjdCcsIHNob3dfTk5fbmV0d29yayA9IFQpCmBgYAoKCgojIERpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcwpOb3cgd2UgaGF2ZSBjbHVzdGVyZWQgdGhlIGNlbGxzLCB3ZSBuZWVkIHRvIGZpbmQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGJldHdlZW4gdGhlIGlkZW50aWZpZWQgbmFtZWQgY2x1c3RlcnMsIGluIHRoaXMgY2FzZSBMZWlkZW4gY2x1c3RlcnMuCioqbWV0aG9kKiogLSBNZXRob2QgdG8gdXNlIGZyb3IgdGhlIHRoZSBkZXRlY3Rpb24gb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGZlYXR1cmVzLCBjYW4gc2VsZWN0ICJzY3JhbiIsICJnaW5pIiBvciAibWFzdCIuCioqZXhwcmVzc2lvbl92YWx1ZXMqKiAtIEZlYXR1cmUgZXhwZXNzaW9uIHZhbHVlcyB0byB1c2UsIHNlbGVjdCBlaXRoZXIgIm5vcm1hbGl6ZWQiLCAic2NhbGVkIiBvciAiY3VzdG9tIi4KCmBgYHtyfQpTVF9zY3Jhbl9tYXJrZXJzX3N1YmNsdXN0ZXJzIDwtIGZpbmRNYXJrZXJzX29uZV92c19hbGwoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gInNjcmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbl92YWx1ZXMgPSJub3JtYWxpemVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1uID0gImxlaWRlbl8wLjRfMTAwMCIpCmBgYAoKQ29ycmVsYXRpb24gYmV0d2VlbiB0b3Agc2VsZWN0ZWQgbWFya2VyIGdlbmVzIGFuZCBpZGVudGlmaWVkIGNsdXN0ZXJzCmBgYHtyfQpTVF90b3A1Z2VuZXMgPC0gU1Rfc2NyYW5fbWFya2Vyc19zdWJjbHVzdGVyc1ssIGhlYWQoLlNELCAzKSxieSA9ICJjbHVzdGVyIl0kZmVhdHMgCgpwbG90TWV0YURhdGFIZWF0bWFwKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwKICAgICAgICAgICAgICAgICAgICBzZWxlY3RlZF9mZWF0cyA9IFNUX3RvcDVnZW5lcywKICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV9jb2xzID0gYygibGVpZGVuXzAuNF8xMDAwIikpCmBgYAoKCiMgU3BhdGlhbCBkaW1lbnNpb24gcGxvdApgYGB7cn0KIyBzcGF0aWFsIGFuZCBkaW1lbnNpb24gcGxvdHMKc3BhdGlhbF9kaW1fcGxvdCA8LXNwYXREaW1QbG90KGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjZWxsX2NvbG9yID0gJ2xlaWRlbl8wLjRfMTAwMCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaW1fcG9pbnRfc2l6ZSA9IDIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BhdF9wb2ludF9zaXplID0gMi41KQoKc3BhdGlhbF9kaW1fcGxvdCAKYGBgCgpgYGB7cn0Kc3BhdERpbVBsb3QoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgY2VsbF9jb2xvciA9ICducl9mZWF0cycsIAogICAgICAgICAgICBjb2xvcl9hc19mYWN0b3IgPSBGLAogICAgICAgICAgICBkaW1fcG9pbnRfc2l6ZSA9IDIsIAogICAgICAgICAgICBzcGF0X3BvaW50X3NpemUgPSAyLjUpCmBgYAoKYGBge3J9CiMgZGltZW5zaW9uIHBsb3RzIGdyb3VwZWQgYnkgY2x1c3RlcgpzcGF0UGxvdDJEKHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICBjZWxsX2NvbG9yID0gJ2xlaWRlbl8wLjRfMTAwMCcsCiAgICAgICAgICAgY29vcmRfZml4X3JhdGlvID0gMSkKYGBgCgpgYGB7cn0Kc3BhdFBsb3QyRCh2aXNpdW1fZ2lvdHRvX29iamVjdCwgCiAgICAgICAgICAgY2VsbF9jb2xvciA9ICdsZWlkZW5fMC40XzEwMDAnLAogICAgICAgICAgIGdyb3VwX2J5ID0gJ2xlaWRlbl8wLjRfMTAwMCcsIAogICAgICAgICAgIGNvb3JkX2ZpeF9yYXRpbyA9IDEsCiAgICAgICAgICAgY293X25fY29sID0gNiwgCiAgICAgICAgICAgc2hvd19sZWdlbmQgPSBGLAogICAgICAgICAgIHNhdmVfcGFyYW0gPSBsaXN0KGJhc2Vfd2lkdGggPSAxNCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFzZV9oZWlnaHQgPSAxNCkpCmBgYAoKYGBge3J9CnNwYXRQbG90MkQodmlzaXVtX2dpb3R0b19vYmplY3QsIGNlbGxfY29sb3IgPSAnbGVpZGVuXzAuNF8xMDAwJywKICAgICAgICAgICBzZWxlY3RfY2VsbF9ncm91cHMgPSBjKCc4JywnNCcpLCBjb29yZF9maXhfcmF0aW8gPSAxLCBzaG93X290aGVyX2NlbGxzID0gVFJVRSwKICAgICAgICAgICBjZWxsX2NvbG9yX2NvZGUgPSBjKCAiOCIgPSAicmVkIiwiNCIgPSAiZ3JlZW40IiksIG90aGVyX2NlbGxfY29sb3IgPSAiZ3JleSIsIG90aGVyX3BvaW50X3NpemUgPSAxLjUsCiAgICAgICAgICAgc2F2ZV9wYXJhbSA9IGxpc3QoYmFzZV93aWR0aCA9IDcsIGJhc2VfaGVpZ2h0ID0gNykpCmBgYAoKYGBge3J9CiMgY3JlYXRlIGFuZCBzaG93IHN1YnNldCwgdXNlIHRoZSBjb29yZGlhbnRlcyBmcm9tIHBsb3QgYWJvdmUKREdfc3Vic2V0ID0gc3Vic2V0R2lvdHRvTG9jcyh2aXNpdW1fZ2lvdHRvX29iamVjdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICB4X21heCA9IDEwMDAsIHhfbWluID0gNTAwLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHlfbWF4ID0gLTgwMCwgeV9taW4gPSAtMTIwMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm5fZ29iamVjdCA9IFRSVUUpCgpzcGF0RGltUGxvdChnb2JqZWN0ID0gREdfc3Vic2V0LCBjZWxsX2NvbG9yID0gImxlaWRlbl8wLjRfMTAwMCIsIHNwYXRfcG9pbnRfc2l6ZSA9IDUpCmBgYAoKIyBNYXJrZXIgR2VuZSBEZXRlY3Rpb24KR2luaSBtYXJrZXJzIC0gSmlhbmcsIEwuLCBDaGVuLCBILiwgUGluZWxsbywgTC4gZXQgYWwuIEdpbmlDbHVzdDogZGV0ZWN0aW5nIHJhcmUgY2VsbCB0eXBlcyBmcm9tIHNpbmdsZS1jZWxsIGdlbmUgZXhwcmVzc2lvbiBkYXRhIHdpdGggR2luaSBpbmRleC4gR2Vub21lIEJpb2wgMTcsIDE0NCAoMjAxNikuIGh0dHBzOi8vZG9pLm9yZy8xMC4xMTg2L3MxMzA1OS0wMTYtMTAxMC00CgpgYGB7cn0KZ2luaV9tYXJrZXJzX3N1YmNsdXN0ZXJzID0gZmluZE1hcmtlcnNfb25lX3ZzX2FsbChnb2JqZWN0ID0gdmlzaXVtX2dpb3R0b19vYmplY3QsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gJ2dpbmknLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4cHJlc3Npb25fdmFsdWVzID0gJ25vcm1hbGl6ZWQnLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1uID0gJ2xlaWRlbl8wLjRfMTAwMCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluX2ZlYXRzID0gMjAsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWluX2V4cHJfZ2luaV9zY29yZSA9IDAuNSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5fZGV0X2dpbmlfc2NvcmUgPSAwLjUpCnRvcGdlbmVzX2dpbmkgPSBnaW5pX21hcmtlcnNfc3ViY2x1c3RlcnNbLCBoZWFkKC5TRCwgMiksIGJ5ID0gJ2NsdXN0ZXInXSRmZWF0cwoKIyB2aW9saW5wbG90CnZpb2xpblBsb3QodmlzaXVtX2dpb3R0b19vYmplY3QsIGZlYXRzID0gdW5pcXVlKHRvcGdlbmVzX2dpbmkpLCBjbHVzdGVyX2NvbHVtbiA9ICdsZWlkZW5fMC40XzEwMDAnLAogICAgICAgICAgIHN0cmlwX3RleHQgPSA4LCBzdHJpcF9wb3NpdGlvbiA9ICdyaWdodCcsCiAgICAgICAgICAgc2F2ZV9wYXJhbSA9IGxpc3QoYmFzZV93aWR0aCA9IDUsIGJhc2VfaGVpZ2h0ID0gMjApKQpgYGAKCmBgYHtyfQojIGNsdXN0ZXIgaGVhdG1hcApwbG90TWV0YURhdGFIZWF0bWFwKHZpc2l1bV9naW90dG9fb2JqZWN0LCBzZWxlY3RlZF9mZWF0cyA9IHVuaXF1ZSh0b3BnZW5lc19naW5pKSwKICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV9jb2xzID0gYygnbGVpZGVuXzAuNF8xMDAwJyksCiAgICAgICAgICAgICAgICAgICAgeF90ZXh0X3NpemUgPSAxMCwgeV90ZXh0X3NpemUgPSAxMCkKYGBgCgpgYGB7cn0KIyB1bWFwIHBsb3RzCmRpbUZlYXRQbG90MkQodmlzaXVtX2dpb3R0b19vYmplY3QsIGV4cHJlc3Npb25fdmFsdWVzID0gJ3NjYWxlZCcsCiAgICAgICAgICAgICAgZmVhdHMgPSBnaW5pX21hcmtlcnNfc3ViY2x1c3RlcnNbLCBoZWFkKC5TRCwgMSksIGJ5ID0gJ2NsdXN0ZXInXSRmZWF0cywKICAgICAgICAgICAgICBjb3dfbl9jb2wgPSA0LCBwb2ludF9zaXplID0gMC43NSwKICAgICAgICAgICAgICBzYXZlX3BhcmFtID0gbGlzdChiYXNlX3dpZHRoID0gOCwgYmFzZV9oZWlnaHQgPSA4KSkKYGBgCgoKU2NyYW4gbWFya2VyIGRldGVjdGlvbgpgYGB7cn0KIyBTY3JhbiBNYXJrZXJzCnNjcmFuX21hcmtlcnNfc3ViY2x1c3RlcnMgPSBmaW5kTWFya2Vyc19vbmVfdnNfYWxsKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0aG9kID0gJ3NjcmFuJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbl92YWx1ZXMgPSAnbm9ybWFsaXplZCcsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1uID0gJ2xlaWRlbl8wLjRfMTAwMCcpCnRvcGdlbmVzX3NjcmFuID0gc2NyYW5fbWFya2Vyc19zdWJjbHVzdGVyc1ssIGhlYWQoLlNELCAyKSwgYnkgPSAnY2x1c3RlciddJGZlYXRzCgojIHZpb2xpbnBsb3QKdmlvbGluUGxvdCh2aXNpdW1fZ2lvdHRvX29iamVjdCwgZmVhdHMgPSB1bmlxdWUodG9wZ2VuZXNfc2NyYW4pLCBjbHVzdGVyX2NvbHVtbiA9ICdsZWlkZW5fMC40XzEwMDAnLAogICAgICAgICAgIHN0cmlwX3RleHQgPSAxMCwgc3RyaXBfcG9zaXRpb24gPSAncmlnaHQnLAogICAgICAgICAgIHNhdmVfcGFyYW0gPSBsaXN0KGJhc2Vfd2lkdGggPSA1LCBiYXNlX2hlaWdodCA9IDIwKSkKYGBgCgpgYGB7cn0KIyBjbHVzdGVyIGhlYXRtYXAKcGxvdE1ldGFEYXRhSGVhdG1hcCh2aXNpdW1fZ2lvdHRvX29iamVjdCwgc2VsZWN0ZWRfZmVhdHMgPSB0b3BnZW5lc19zY3JhbiwKICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YV9jb2xzID0gYygnbGVpZGVuXzAuNF8xMDAwJykpCmBgYAoKYGBge3J9CiMgdW1hcCBwbG90cwpkaW1GZWF0UGxvdDJEKHZpc2l1bV9naW90dG9fb2JqZWN0LCBleHByZXNzaW9uX3ZhbHVlcyA9ICdzY2FsZWQnLAogICAgICAgICAgICAgIGZlYXRzID0gc2NyYW5fbWFya2Vyc19zdWJjbHVzdGVyc1ssIGhlYWQoLlNELCAxKSwgYnkgPSAnY2x1c3RlciddJGZlYXRzLAogICAgICAgICAgICAgIGNvd19uX2NvbCA9IDMsIHBvaW50X3NpemUgPSAxLAogICAgICAgICAgICAgIHNhdmVfcGFyYW0gPSBsaXN0KGJhc2Vfd2lkdGggPSA4LCBiYXNlX2hlaWdodCA9IDgpKQoKcERhdGFEVCh2aXNpdW1fZ2lvdHRvX29iamVjdCkKYGBgCgpDZWxsIHR5cGUgYW5ub3RhdGlvbgpQQUdFIGVucmljaG1lbnQKCkNyZWF0ZSBsaXN0cyBvZiBjZWxsIHNpZ25hdHVyZSBnZW5lcwpgYGB7cn0KIyBHcmFudWxlIG5ldXJvbnMKZ3Jhbl9tYXJrZXJzIDwtIGMoIk5yM2MyIiwgIkdhYnJhNSIsICJUdWJnY3AyIiwgIkFoY3lsMiIsCiAgICAgICAgICAgICAgICAgIklzbHIyIiwgIlJhc2wxMGEiLCAiVG1lbTExNCIsICJCaGxoZTIyIiwgCiAgICAgICAgICAgICAgICAgIk50ZjMiLCAiQzFxbDIiKQoKIyBPbGlnbyBkZW5kcm9jeXRlcwpvbGlnb19tYXJrZXJzIDwtIGMoIkVmaGQxIiwgIkgyLUFiMSIsICJFbnBwNiIsICJOaW5qMiIsCiAgICAgICAgICAgICAgICAgICJCbXA0IiwgIlRuciIsICJIYXBsbjIiLCAiTmV1NCIsCiAgICAgICAgICAgICAgICAgICJXZmRjMTgiLCAiQ2NwMTEwIikgICAgICAgIAoKIyBEaSBtZXNlbmNoZXBoYWxvbgpkaV9tZXNlbmNoX21hcmtlcnMgPC0gYygiQ2FydHB0IiwgIlNjbjFhIiwgIkx5cGQ2YiIsICAiRHJkNSIsCiAgICAgICAgICAgICAgICAgICAgICAgIkdwcjg4IiwgIlBsY3hkMiIsICJDcG5lNyIsICJQb3U0ZjEiLAogICAgICAgICAgICAgICAgICAgICAgICJDdHhuMiIsICJXbnQ0IikKCiMgQ3JlYXRlIGEgYmluYXJ5IG1hdHJpeCBvZiBjZWxsIHNpZ25hdHVyZXMKc2lnbmF0dXJlX21hdHJpeCA8LSBtYWtlU2lnbk1hdHJpeFBBR0Uoc2lnbl9uYW1lcyA9IGMoJ0dyYW51bGVfbmV1cm9ucycsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ09saWdvX2RlbmRyb2N5dGVzJywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnZGlfbWVzZW5jaGVwaGFsb24nKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaWduX2xpc3QgPSBsaXN0KGdyYW5fbWFya2VycywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9saWdvX21hcmtlcnMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaV9tZXNlbmNoX21hcmtlcnMpKQoKc2lnbl9tYXRyaXhfcGF0aCA8LSBzeXN0ZW0uZmlsZSgiZXh0ZGF0YSIsICJzaWdfbWF0cml4LnR4dCIsIHBhY2thZ2UgPSAnR2lvdHRvJykKCmJyYWluX3NjX21hcmtlcnMgPC0gZGF0YS50YWJsZTo6ZnJlYWQoc2lnbl9tYXRyaXhfcGF0aCkKCnNpZ19tYXRyaXggPC0gYXMubWF0cml4KGJyYWluX3NjX21hcmtlcnNbLC0xXSk7IHJvd25hbWVzKHNpZ19tYXRyaXgpID0gYnJhaW5fc2NfbWFya2VycyRFdmVudApgYGAKCgpgYGB7cn0KIyBFbnJpY2htZW50IHRlc3Qgd2l0aCBQQUdFCgojIHJ1blNwYXRpYWxFbnJpY2goKSBjYW4gYWxzbyBiZSB1c2VkIGFzIGEgd3JhcHBlciBmb3IgYWxsIGN1cnJlbnRseSBwcm92aWRlZCBlbnJpY2htZW50IG9wdGlvbnMKdmlzaXVtX2dpb3R0b19vYmplY3QgPSBydW5QQUdFRW5yaWNoKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgc2lnbl9tYXRyaXggPSBzaWdfbWF0cml4KQoKIyBoZWF0bWFwIG9mIGVucmljaG1lbnQgdmVyc3VzIGFubm90YXRpb24gKGUuZy4gY2x1c3RlcmluZyByZXN1bHQpCmNlbGxfdHlwZXMgPSBjb2xuYW1lcyhzaWdfbWF0cml4KQpwbG90TWV0YURhdGFDZWxsc0hlYXRtYXAoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGFfY29scyA9ICdsZWlkZW5fMC40XzEwMDAnLAogICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVfY29scyA9IGNlbGxfdHlwZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICBzcGF0X2Vucl9uYW1lcyA9ICdQQUdFJywKICAgICAgICAgICAgICAgICAgICAgICAgIHhfdGV4dF9zaXplID0gOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICB5X3RleHRfc2l6ZSA9IDgpCmBgYAoKYGBge3J9CiMgVmlzdWFsaXphdGlvbnMKY2VsbF90eXBlc19zdWJzZXQgPSBjb2xuYW1lcyhzaWdfbWF0cml4KVsxOjEwXQpzcGF0Q2VsbFBsb3QoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LCAKICAgICAgICAgICAgIHNwYXRfZW5yX25hbWVzID0gJ1BBR0UnLAogICAgICAgICAgICAgY2VsbF9hbm5vdGF0aW9uX3ZhbHVlcyA9IGNlbGxfdHlwZXNfc3Vic2V0LAogICAgICAgICAgICAgY293X25fY29sID0gNCxjb29yZF9maXhfcmF0aW8gPSBOVUxMLCBwb2ludF9zaXplID0gMC43NSkKYGBgCgpgYGB7cn0KY2VsbF90eXBlc19zdWJzZXQgPSBjb2xuYW1lcyhzaWdfbWF0cml4KVsxMToyMF0Kc3BhdENlbGxQbG90KGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgc3BhdF9lbnJfbmFtZXMgPSAnUEFHRScsIAogICAgICAgICAgICAgY2VsbF9hbm5vdGF0aW9uX3ZhbHVlcyA9IGNlbGxfdHlwZXNfc3Vic2V0LCBjb3dfbl9jb2wgPSA0LAogICAgICAgICAgICAgY29vcmRfZml4X3JhdGlvID0gTlVMTCwgcG9pbnRfc2l6ZSA9IDAuNzUsIAogICAgICAgICAgICAgc2F2ZV9wYXJhbSA9IGxpc3Qoc2F2ZV9uYW1lPSI3X2Nfc3BhdGNlbGxwbG90XzIiKSkKYGBgCgoKYGBge3J9CiMgZG93bmxvYWQgZGF0YSB0byByZXN1bHRzIGRpcmVjdG9yeSAjIyMjCiMgaWYgd2dldCBpcyBpbnN0YWxsZWQsIHNldCBtZXRob2QgPSAnd2dldCcKIyBpZiB5b3UgcnVuIGludG8gYXV0aGVudGljYXRpb24gaXNzdWVzIHdpdGggd2dldCwgdGhlbiBhZGQgIiBleHRyYSA9ICctLW5vLWNoZWNrLWNlcnRpZmljYXRlJyAiCgpnZXRTcGF0aWFsRGF0YXNldChkYXRhc2V0ID0gJ3NjUk5BX21vdXNlX2JyYWluJywgZGlyZWN0b3J5ID0gcmVzdWx0c19mb2xkZXIpCgpzY19leHByZXNzaW9uIDwtIHBhc3RlMChyZXN1bHRzX2ZvbGRlciwgIi9icmFpbl9zY19leHByZXNzaW9uX21hdHJpeC50eHQuZ3oiKQpzY19tZXRhZGF0YSA8LSBwYXN0ZTAocmVzdWx0c19mb2xkZXIsIi9icmFpbl9zY19tZXRhZGF0YS5jc3YiKQoKZ2lvdHRvX1NDIDwtIGNyZWF0ZUdpb3R0b09iamVjdCgKICBleHByZXNzaW9uID0gc2NfZXhwcmVzc2lvbiwKICBpbnN0cnVjdGlvbnMgPSBpbnN0cnMKKQoKZ2lvdHRvX1NDIDwtIGFkZENlbGxNZXRhZGF0YShnaW90dG9fU0MsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3X21ldGFkYXRhID0gZGF0YS50YWJsZTo6ZnJlYWQoc2NfbWV0YWRhdGEpKQoKZ2lvdHRvX1NDIDwtIG5vcm1hbGl6ZUdpb3R0byhnaW90dG9fU0MpCmBgYAoKYGBge3J9CiMgMS4yIFtzaG9ydGN1dF0gZnVsbHkgcHJlLXByZXBhcmVkIG1hdHJpeCBmb3IgYWxsIGNlbGwgdHlwZXMKc2lnbl9tYXRyaXhfcGF0aCA9IHN5c3RlbS5maWxlKCJleHRkYXRhIiwgInNpZ19tYXRyaXgudHh0IiwgcGFja2FnZSA9ICdHaW90dG8nKQpicmFpbl9zY19tYXJrZXJzID0gZGF0YS50YWJsZTo6ZnJlYWQoc2lnbl9tYXRyaXhfcGF0aCkKUEFHRV9tYXRyaXhfMiA9IGFzLm1hdHJpeChicmFpbl9zY19tYXJrZXJzWywtMV0pCnJvd25hbWVzKFBBR0VfbWF0cml4XzIpID0gYnJhaW5fc2NfbWFya2VycyRFdmVudAoKCiMgLS0tCgojIE1ha2UgUEFHRSBtYXRyaXggZnJvbSBzaW5nbGUgY2VsbCBkYXRhc2V0Cm1hcmtlcnNfc2NyYW4gPSBmaW5kTWFya2Vyc19vbmVfdnNfYWxsKGdvYmplY3Q9Z2lvdHRvX1NDLCBtZXRob2Q9InNjcmFuIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZXhwcmVzc2lvbl92YWx1ZXM9Im5vcm1hbGl6ZWQiLCBjbHVzdGVyX2NvbHVtbiA9ICJDbGFzcyIsIG1pbl9mZWF0cz0zKQp0b3BfbWFya2VycyA8LSBtYXJrZXJzX3NjcmFuWywgaGVhZCguU0QsIDEwKSwgYnk9ImNsdXN0ZXIiXQpjZWxsdHlwZXM8LWxldmVscyhmYWN0b3IobWFya2Vyc19zY3JhbiRjbHVzdGVyKSkKc2lnbl9saXN0PC1saXN0KCkKZm9yIChpIGluIDE6bGVuZ3RoKGNlbGx0eXBlcykpewogIHNpZ25fbGlzdFtbaV1dPC10b3BfbWFya2Vyc1t3aGljaCh0b3BfbWFya2VycyRjbHVzdGVyID09IGNlbGx0eXBlc1tpXSksXSRmZWF0cwp9CgpQQUdFX21hdHJpeF8zID0gbWFrZVNpZ25NYXRyaXhQQUdFKHNpZ25fbmFtZXMgPSBjZWxsdHlwZXMsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2lnbl9saXN0ID0gc2lnbl9saXN0KQoKIyBFbnJpY2htZW50IHRlc3Qgd2l0aCBQQUdFCgojIHJ1blNwYXRpYWxFbnJpY2goKSBjYW4gYWxzbyBiZSB1c2VkIGFzIGEgd3JhcHBlciBmb3IgYWxsIGN1cnJlbnRseSBwcm92aWRlZCBlbnJpY2htZW50IG9wdGlvbnMKdmlzaXVtX2dpb3R0b19vYmplY3QgPSBydW5QQUdFRW5yaWNoKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwgc2lnbl9tYXRyaXggPSBQQUdFX21hdHJpeF8yKQoKIyAxLjUgaGVhdG1hcCBvZiBlbnJpY2htZW50IHZlcnN1cyBhbm5vdGF0aW9uIChlLmcuIGNsdXN0ZXJpbmcgcmVzdWx0KQpjZWxsX3R5cGVzX1BBR0UgPSBjb2xuYW1lcyhQQUdFX21hdHJpeF8yKQpwbG90TWV0YURhdGFDZWxsc0hlYXRtYXAoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGFfY29scyA9ICdsZWlkZW5fY2x1cycsCiAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZV9jb2xzID0gY2VsbF90eXBlc19QQUdFLAogICAgICAgICAgICAgICAgICAgICAgICAgc3BhdF9lbnJfbmFtZXMgPSAnUEFHRScsCiAgICAgICAgICAgICAgICAgICAgICAgICB4X3RleHRfc2l6ZSA9IDgsCiAgICAgICAgICAgICAgICAgICAgICAgICB5X3RleHRfc2l6ZSA9IDgpCmBgYAoKYGBge3J9CiMgVmlzdWFsaXphdGlvbnMKc3BhdENlbGxQbG90MkQoZ29iamVjdCA9IHZpc2l1bV9naW90dG9fb2JqZWN0LAogICAgICAgICAgICAgICBzcGF0X2Vucl9uYW1lcyA9ICdQQUdFJywKICAgICAgICAgICAgICAgY2VsbF9hbm5vdGF0aW9uX3ZhbHVlcyA9IGNlbGxfdHlwZXNfUEFHRVsxOjJdLAogICAgICAgICAgICAgICBjb3dfbl9jb2wgPSAyLGNvb3JkX2ZpeF9yYXRpbyA9IDEsIHBvaW50X3NpemUgPSAxLjI1LCBzaG93X2xlZ2VuZCA9IFQpCmBgYAoKYGBge3J9CnNwYXREaW1DZWxsUGxvdDJEKGdvYmplY3QgPSB2aXNpdW1fZ2lvdHRvX29iamVjdCwKICAgICAgICAgICAgICAgICAgc3BhdF9lbnJfbmFtZXMgPSAnUEFHRScsCiAgICAgICAgICAgICAgICAgIGNlbGxfYW5ub3RhdGlvbl92YWx1ZXMgPSBjZWxsX3R5cGVzX1BBR0VbMToyXSwKICAgICAgICAgICAgICAgICAgY293X25fY29sID0gMSwgc3BhdF9wb2ludF9zaXplID0gMSwKICAgICAgICAgICAgICAgICAgcGxvdF9hbGlnbm1lbnQgPSAnaG9yaXpvbnRhbCcsCiAgICAgICAgICAgICAgICAgIHNhdmVfcGFyYW0gPSBsaXN0KGJhc2Vfd2lkdGg9NywgYmFzZV9oZWlnaHQ9MTApKQpgYGAKCmBgYHtyfQpSRGF0YS5uYW1lIDwtICJnaW90dG9fc3BhdGlhbF90cmFuc2NyaXB0b21pY3MiCnNhdmUuaW1hZ2UoUkRhdGEubmFtZSkKYGBgCgoKYGBge3J9CnNlc3Npb25JbmZvKCkKYGBgCgo=